package com.xms.queryview.api.controller;

import com.xms.core.components.QueryColumnSortInfo;
import com.xms.core.model.PagedList;
import com.xms.core.module.ModuleCollection;
import com.xms.queryview.api.model.DataListModel;
import com.xms.queryview.api.model.EntityGridModel;
import com.xms.queryview.api.model.RecordsDialogModel;
import com.xms.queryview.api.model.RecordsDialogResultModel;
import com.xms.queryview.core.QueryViewDefaults;
import com.xms.queryview.entity.QueryView;
import com.xms.queryview.service.IGridService;
import com.xms.queryview.service.IQueryViewFinderService;
import com.xms.ribbonbutton.core.RibbonButtonArea;
import com.xms.ribbonbutton.entity.RibbonButton;
import com.xms.ribbonbutton.service.IRibbonButtonFinderService;
import com.xms.schema.entity.RelationShip;
import com.xms.schema.service.relationship.IRelationShipFinderService;
import com.xms.sdk.core.DynamicData;
import com.xms.sdk.core.query.ConditionExpression;
import com.xms.sdk.core.query.ConditionOperator;
import com.xms.sdk.core.query.FilterExpression;
import com.xms.sdk.extensions.IQueryMetadataFinder;
import com.xms.sdk.query.QueryMetadataDescriptor;
import com.xms.sdk.service.FetchDescriptor;
import com.xms.sdk.service.IFetchDataService;
import com.xms.security.service.dataauth.IObjectAuthorizationFilter;
import com.xms.security.service.dataauth.IRoleObjectAccessService;
import com.xms.utils.CollectionUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import com.xms.web.framework.controller.ApiBaseController;
import com.xms.web.framework.model.JsonResultObject;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 * GridViewController
 * </p>
 *
 * @author migo
 * @since 2021/9/21
 */
@RestController
@RequestMapping("{org}/api/entity")
public class GridViewController extends ApiBaseController {
    private IQueryViewFinderService _queryViewFinderService;
    private IRibbonButtonFinderService _ribbonbuttonFinderService;
    private IRelationShipFinderService _relationShipFinderService;
    private IGridService _gridService;
    private IFetchDataService _fetchDataService;
    private IRoleObjectAccessService _roleObjectAccessService;
    private IObjectAuthorizationFilter _objectAuthorizationFilter;
    private IQueryMetadataFinder _queryMetadataFinder;

    @Autowired
    public GridViewController(IQueryViewFinderService queryViewFinderService
            , IRibbonButtonFinderService ribbonbuttonFinderService
            , IRelationShipFinderService relationShipFinderService
            , IGridService gridService
            , IRoleObjectAccessService roleObjectAccessService
            , IFetchDataService fetchDataService
            , IObjectAuthorizationFilter objectAuthorizationFilter
            , IQueryMetadataFinder queryMetadataFinder) {
        _gridService = gridService;
        _fetchDataService = fetchDataService;
        _queryViewFinderService = queryViewFinderService;
        _ribbonbuttonFinderService = ribbonbuttonFinderService;
        _relationShipFinderService = relationShipFinderService;
        _roleObjectAccessService = roleObjectAccessService;
        _objectAuthorizationFilter = objectAuthorizationFilter;
        _queryMetadataFinder = queryMetadataFinder;
    }

    @ApiOperation("单据体记录列表")
    @PostMapping("rendergridview")
    public JsonResultObject renderGridView(@RequestBody DataListModel model) throws Exception {
        QueryView queryView = null;
        if (UUIDUtil.notEmpty(model.QueryViewId)) {
            queryView = _queryViewFinderService.getById(model.QueryViewId);
        } else if (UUIDUtil.notEmpty(model.EntityId)) {
            queryView = _queryViewFinderService.getDefaultView(model.EntityId);
        } else if (StringUtil.notEmpty(model.EntityName)) {
            queryView = _queryViewFinderService.getDefaultView(model.EntityName);
        }
        if (queryView == null) {
            return JNotFound();
        }
        if (!queryView.getIsdefault() && queryView.getAuthorizationenabled()) {
            if (!_objectAuthorizationFilter.valid(queryView.getQueryviewid(), ModuleCollection.getIdentity(QueryViewDefaults.MODULE_NAME), _currentUser.getRoles())) {
                return JUnauthorized();
            }
        }
        EntityGridModel result = new EntityGridModel();
        result.QueryView = queryView;
        result.EntityId = queryView.getEntityid();
        result.sortdirection = model.sortdirection;
        result.sortby = model.sortby;
        result.page = model.page;
        result.pagesize = model.pagesize;

        FetchDescriptor fetch = new FetchDescriptor();
        fetch.page = model.page;
        fetch.pageSize = model.pagesize;
        fetch.fetchConfig = queryView.getFetchconfig();
        fetch.getAll = !model.PagingEnabled;
        if (model.issortbyseted) {
            QueryColumnSortInfo sort = new QueryColumnSortInfo(model.sortby, model.sortdirection == 0);
            fetch.sort = sort;
        }
        //查询关键字
        if (StringUtil.notEmpty(model.Q)) {
            fetch.keyword = model.Q;
            fetch.field = model.QField;
        }
        boolean canFetch = true;
        //filter by relationship
        if (StringUtil.notEmpty(model.RelationShipName)) {
            RelationShip relationship = _relationShipFinderService.getByName(model.RelationShipName);
            if (relationship == null || !UUIDUtil.notEmpty(model.ReferencedRecordId)) {
                if (model.Filter == null) {
                    model.Filter = new FilterExpression();
                }
                ConditionExpression condition = new ConditionExpression(relationship.getReferencingattributename(), ConditionOperator.Equal, model.ReferencedRecordId);
                model.Filter.addCondition(condition);
            }
            result.RelationShipMeta = relationship;
        }
        if (StringUtil.notEmpty(model.RelationShipName) && UUIDUtil.isEmpty(model.ReferencedRecordId)) {
            //如果被引用ID为空，则不查询数据
            canFetch = false;
        }
        fetch.filter = model.Filter;
        QueryMetadataDescriptor metadataDescriptor = _queryMetadataFinder.getAll(fetch.query);
        if (canFetch) {
            fetch.user = _currentUser;
            PagedList<DynamicData> datas = _fetchDataService.execute(fetch);
            if (model.OnlyData) {
                return JOk(datas);
            }
            result.items = datas.items;
            result.totalitems = datas.totalitems;
            result.totalpages = datas.totalpages;
        }
        result.Grid = _gridService.Build(queryView, metadataDescriptor.entityList, metadataDescriptor.attributeList);
        result.EntityList = metadataDescriptor.entityList;
        result.AttributeList = metadataDescriptor.attributeList;
        result.RelationShipList = metadataDescriptor.relationShipList;
        List<RibbonButton> buttons = _ribbonbuttonFinderService.getByArea(model.EntityId, RibbonButtonArea.SubGrid);
        if (CollectionUtil.notEmpty(buttons)) {
            result.RibbonButtons = buttons;
        }
        if (model.issortbyseted == false) {
            if (CollectionUtil.notEmpty(fetch.query.Orders)) {
                result.sortby = fetch.query.Orders.get(0).AttributeName;
                result.sortdirection = fetch.query.Orders.get(0).OrderType.val();
            }
        }
        return JOk(result);
    }

    @ApiOperation("选择实体数据对话框")
    @PostMapping("recordsdialog")
    public JsonResultObject recordsDialog(@RequestBody RecordsDialogModel model) throws Exception {
        QueryView queryView = null;
        if (UUIDUtil.notEmpty(model.QueryId)) {
            queryView = _queryViewFinderService.getById(model.QueryId);
        } else if (UUIDUtil.notEmpty(model.EntityId)) {
            queryView = _queryViewFinderService.getDefaultView(model.EntityId);
        } else if (StringUtil.notEmpty(model.EntityName)) {
            queryView = _queryViewFinderService.getDefaultView(model.EntityName);
        }
        if (queryView == null) {
            return JNotFound();
        }
        RecordsDialogResultModel result = new RecordsDialogResultModel();
        result.QueryView = queryView;
        result.page = model.page;
        result.pagesize = model.pagesize;

        FetchDescriptor fetch = new FetchDescriptor();
        fetch.user = _currentUser;
        fetch.page = model.page;
        fetch.pageSize = model.pagesize;
        fetch.fetchConfig = queryView.getFetchconfig();

        QueryColumnSortInfo sort = new QueryColumnSortInfo(model.sortby, model.sortdirection == 0);
        fetch.sort = sort;

        if (StringUtil.notEmpty(model.Q)) {
            fetch.keyword = model.Q;
            fetch.field = model.QField;
        }
        if (model.Filter == null) {
            model.Filter = new FilterExpression();
        }
        //filter disabled records
        if (model.OnlyEnabledRecords) {
            if (CollectionUtil.isEmpty(model.Filter.Conditions)
                    || !model.Filter.Conditions.stream().anyMatch(n -> n.AttributeName.equalsIgnoreCase("statecode"))) {
                model.Filter.addCondition("statecode", ConditionOperator.Equal, true);
            }
        }
        //filter by relationship
        if (StringUtil.notEmpty(model.RelationShipName)) {
            RelationShip relationship = _relationShipFinderService.getByName(model.RelationShipName);
            if (relationship == null || !UUIDUtil.notEmpty(model.ReferencedRecordId)) {
                ConditionExpression condition = new ConditionExpression(relationship.getReferencingattributename(), ConditionOperator.Equal, model.ReferencedRecordId);
                model.Filter.addCondition(condition);
            }
            result.RelationShipMeta = relationship;
        }
        fetch.filter = model.Filter;

        PagedList<DynamicData> datas = _fetchDataService.execute(fetch);
        QueryMetadataDescriptor metadataDescriptor = _queryMetadataFinder.getAll(fetch.query);
        result.Grid = _gridService.Build(queryView, metadataDescriptor.entityList, metadataDescriptor.attributeList);
        result.EntityList = metadataDescriptor.entityList;
        result.AttributeList = metadataDescriptor.attributeList;
        result.RelationShipList = metadataDescriptor.relationShipList;
        result.items = datas.items;
        result.totalitems = datas.totalitems;
        result.totalpages = datas.totalpages;
        if (model.issortbyseted == false) {
            if (CollectionUtil.notEmpty(fetch.query.Orders)) {
                result.sortby = fetch.query.Orders.get(0).AttributeName;
                result.sortdirection = fetch.query.Orders.get(0).OrderType.val();
            }
        }

        return JOk(result);
    }
}
